#include <bitset>
#include <map>
#include <iostream>
#include <memory>
#include <vector>
#include <session.h>
#include "../../c-s/hub/business/dbobject.h"
#include "utils.h"
#include <fstream>

using namespace std;

//unique_ptr<char> encode(Protocal &p)
//{

	//p.head.len = sizeof(p.head) + p.body.size();
	//p.head.version = '1';

	//unique_ptr<char> data(new char[p.head.len]);
	//memcpy(data.get(), &p.head, sizeof(p.head));
	//memcpy(data.get()+sizeof(p.head), &(*p.body.begin()), p.body.size());

	//return data;

//}

//size_t chararr_combined_to_sizet(const char* arr, int beginByteIndex, int size)
//{
	//size_t out = 0;

	//for (int i = beginByteIndex; i < beginByteIndex+size; i++) {
		//out |= (size_t)*(arr+i) << 8*(i-size);
	//}

	//return out;
//}

template<typename T>
void show_struct_memory(const T* v)
{
	const char *s = reinterpret_cast<const char*>(v);
	for (int i=0; i<sizeof(T); i++) {
		bitset<8> bs(s[i]);
		if (i % 4 == 0) {
			cout<<i<<':'<<endl;
		}
		cout<<bs<<endl;
	}
}

void show_memory(char* v, size_t len)
{

	for (int i = 0; i<len; i++) {
		bitset<8> bs(v[i]);
		if (i % 4 == 0) {
			cout<<i<<':'<<endl;
		}
		cout<<bs<<endl;
	}
}

//测试：vector的insert方法是否接收指针
void test_vector_insert()
{
	vector<int> v1(3, 6);
	int arr[3] = {7, 7, 7};
	v1.insert(v1.end(), arr, arr+3);
	for (auto i : v1) {
		cout<<i<<endl;
	}
}


//测试：vector通过指针来初始构造
void test_vector_point_init()
{
	char* a = "hello world";
	vector<char> v1(a, a+11);

	for (auto i : v1) {
		cout<<i<<endl;
	}
}

//测试：unique_ptr作为返回值传出来，是否调用析构
unique_ptr<int> makeint()
{
	unique_ptr<int> ptr(new int(12));
	return ptr;
}
unique_ptr<int> test_unique()
{
	auto i = makeint();
	// auto i = makeint().get();
	cout<<*i<<endl;
	*i = 20;
	cout<<*i<<endl;
	return i;
}

//测试：枚举类型
void test_enum()
{
	enum type {
		MGS_TYPE = '1',
		FILE_TYPE = '2'
	};

	char i = '2';

	switch (i) {
		case MGS_TYPE:
			cout<<"is mgs_TYPE"<<endl;
			break;
		case FILE_TYPE:
			cout<<"is FILE_TYPE"<<endl;
			break;
		default:
			cout<<"is default!!!!"<<endl;
	}
}


//测试：引用的对象在多个线程中的生命周期问题

int& test_ref()
{
	int a = 10;

	return a;
}

void test_sqlite3_orm()
{
		cout<<"hello in main"<<endl;
	std::string vname;	//文件名
	std::string err;	//错误信息
	uint32_t batch;	//文件分节数
	int per = 1024 * 1024;	//1MB传输

		auto user = storage.get_pointer<VideoMetaData>(1);
		if(user) {
			cout << "user = " << user->id << " " << user->name << endl;
			batch = user->size % per ? user->size / per + 1 : user->size / per;
			cout << "size = " <<user->size << " per = " << 1024*1024 <<" batch = "<<batch<<endl;
		}else {
			cout <<"get_pointer return null"<<endl;
		}

}

void test_string_to_macro()
{
#define TOMACR(str) #str

	enum class REV{
		LS = 0,
		PLAY =1,
	};

	string name = "LS";
	cout<<TOMACR(REV::LS)<<endl;
	//ASSERT(TOMACR(REV::LS) == name);
}

#define BUFFSIZE (3*1024*1024)

void test_base64(std::string filename)
{
	ifstream in(filename, ifstream::binary);
	ofstream out("bs64.txt");
	if (in.is_open() && out.is_open()) {
		in.seekg(0, in.end);
		size_t size = in.tellg();
		in.seekg(0, in.beg);

		cout << "猿文件大小: " << size << endl;

		while(!in.eof()) {
			char* buf = new char[BUFFSIZE];
			in.read(buf, BUFFSIZE);
			string o;
			o.resize(Base64::EncodedLength(BUFFSIZE));
			Base64::Encode(buf, BUFFSIZE, &o[0], o.size());
			out << o;
			delete []buf;
		}
		in.close();
	}
	out.close();
}

void test_ffprob(string filename) {
	ifstream in("bs64.txt");
	ofstream out("bs64.mp4", ofstream::binary);
	if (in.is_open() && out.is_open()) {
		in.seekg(0, in.end);
		int length = in.tellg();
		in.seekg(0, in.beg);

		cout << "bs64.txt文件大小 : " << length << endl;

		while(!in.eof()) {
			char * buf = new char[BUFFSIZE];
			in.read(buf, BUFFSIZE);

			string bsin;
			bsin.resize(Base64::DecodedLength(buf, BUFFSIZE));
			Base64::Decode(buf, BUFFSIZE, &bsin[0], bsin.size());
			out << bsin;
			delete [] buf;
		}

		cout << "bs64.mp4文件大小为: " << out.tellp() << endl;

	//release resource
		in.close();
		out.close();
	}
}

int main(int argc, const char* argv[]) {

	//test_char_array_to_int();
	//test_vector_insert();
	//test_vector_point_init();
	//auto j = test_unique();
	//cout<<*j<<endl;

	//test_enum();

	//test_sqlite3_orm();
	// test_string_to_macro();
	test_base64(argv[1]);
	test_ffprob(argv[1]);
	//system("pause");

    // std::map<int, int> m;
    // auto it = m.find(12);
    // if (it == m.end()) {
    //     return -1;
    // }
    return 0;
}
